﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Serialization;
using TravianMiniBot.Entities;
using Action = TravianMiniBot.Entities.Action;

namespace TravianMiniBot
{
    public class QueueService
    {
        public List<QueueItem> AddToQueue(List<QueueItem> queue, Action action)
        {
            var newitem = new QueueItem();
            newitem.Id = Guid.NewGuid();
            newitem.Action = action;

            //Get the last item for the village.
            var lastvillageitem = (from item in queue
                                   where item.Action.TargetVillage.TravianId == action.TargetVillage.TravianId
                                   select item.Time).ToList();

            
            if (lastvillageitem.Count > 0)
            {
                newitem.Time = lastvillageitem.Max().AddMinutes(1);
            }
            else
            {
                newitem.Time = DateTime.Now.AddMinutes(1);
            }
            
            queue.Add(newitem);
            return queue;
        }

        public List<QueueItem> RemoveFromQueue(List<QueueItem> queue, Guid Id)
        {
            queue.RemoveAll( (x) => x.Id == Id);
            return queue;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="queue"></param>
        /// <returns>The time for the next process</returns>
        public void Processqueue(List<QueueItem> queue)
        {
            var sortedlist = from queueitem in queue where queueitem.Time <= DateTime.Now
                             orderby queueitem.Time ascending
                             select queueitem;


            foreach (var item in sortedlist)
            {
                try
                {
                    var diff = item.Action.Execute();
                    //if successful adjust the time of everything else
                    AdjustTime(queue,diff,item.Action.TargetVillage.TravianId);

                }
                catch (Exception ex)
                {
                    AdjustTime(queue, new TimeSpan(0, 0, 1), item.Action.TargetVillage.TravianId);
                    throw new QueueException(string.Format("The task:{0} did not complete",item.Action.Description), ex);
                }
            }
        }

        public void SaveQueue(List<QueueItem> queue)
        {
            
            return;
        }

        public List<QueueItem> LoadQueue()
        {
            return null;
        }

        private void AdjustTime(List<QueueItem> items, TimeSpan allowance, int villageid)
        {
            var itemstoupdate = from item in items
                                where item.Action.TargetVillage.TravianId == villageid
                                select item;

            foreach (var item in itemstoupdate)
            {
                item.Time = item.Time.Add(allowance);
            }

        }
    }
}
